/*
 * Copyright 2008-2010 Daniel Cachapa <cachapa@gmail.com>
 * 
 * This program is distributed under the terms of the GNU General Public License Version 3
 * The license can be read in its entirety in the LICENSE.txt file accompanying this source code,
 * or at: http://www.gnu.org/copyleft/gpl.html
 * 
 * This file is part of Libra.
 *
 * WeightWatch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * WeightWatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the WeightWatch source code. If not, see: http://www.gnu.org/licenses
 */

package net.cachapa.libra.util;

import net.cachapa.libra.Preferences;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

public class UnitManager {
	// Metric
	private static final int METRIC_MIN_WEIGHT = 0;
	private static final int METRIC_MAX_WEIGHT = 200;
	private static final int METRIC_DEFAULT_WEIGHT = 80;
	
	private static final int METRIC_MIN_HEIGHT = 1;
	private static final int METRIC_MAX_HEIGHT = 3;
	private static final float METRIC_DEFAULT_HEIGHT = 1.70f;
	
	private static final int KCAL_PER_KILOGRAM = 7716;
	
	// Imperial
	private static final int IMPERIAL_MIN_WEIGHT = 0;
	private static final int IMPERIAL_MAX_WEIGHT = 440;
	private static final int IMPERIAL_DEFAULT_WEIGHT = 180;
	
	private static final int IMPERIAL_MIN_HEIGHT = 3 * 12;
	private static final int IMPERIAL_MAX_HEIGHT = 10 * 12;
	private static final int IMPERIAL_DEFAULT_HEIGHT = (int) (5.58 * 12);
	
	private static final int KCAL_PER_POUND = 3500;
	
	private static UnitManager instance = null;
	private SharedPreferences prefs;
	private boolean isMetricHeight, isMetricWeight, isStones;
	
	protected UnitManager(Context context) {
		prefs = PreferenceManager.getDefaultSharedPreferences(context);
		isMetricHeight = prefs.getString(Preferences.HEIGHT_UNITS, "meters").equals("meters");
		isMetricWeight = prefs.getString(Preferences.WEIGHT_UNITS, "kilograms").equals("kilograms");
		isStones = prefs.getString(Preferences.WEIGHT_UNITS, "").equals("stones");
	}
	
	public static UnitManager getInstance(Context context) {
		if (instance == null) {
			instance = new UnitManager(context);
		}
		return instance;
	}
	
	public void setMetricHeight(boolean isMetricHeight) {
		this.isMetricHeight = isMetricHeight;
	}
	
	public void setMetricWeight(boolean isMetricWeight) {
		this.isMetricWeight = isMetricWeight;
	}
	
	public void setStones(boolean isStones) {
		this.isStones = isStones;
	}
	
	public String toHeightUnit(float value) {
		value = Util.Round(value, 2);
		if (isMetricHeight) {
			return value + " m";
		}
		return (int)value/12 + "ft " + (int)value%12 + "in";
	}
	
	public String toWeightUnit(float value) {
		value = Util.Round(value, 1);
		if (isMetricWeight) {
			return value + " Kg";
		}
		if (isStones) {
			return (int)value/14 + " st " + Util.Round(value%14, 1);
		}
		return value + " lbs";
	}
	
	public String getHeightUnit() {
		if (isMetricHeight) {
			return "m";
		}
		return "in";
	}
	
	public String getWeightUnit() {
		if (isMetricWeight) {
			return "Kg";
		}
		return "lbs";
	}
	
	public String convertHeightToImperial(float value) {
		double result = value / 0.3048;
		int feet = (int) Math.floor(result);
		int inches = (int) Math.round(((result - feet) * 100) % 12);
		return feet + " ft " + inches + " in";
	}
	
	/***
	 * Converts from inches to feet and inches
	 * @return Int array with feet in position 0 and inches in position 1
	 */
	public int[] inchesToFeetInches(int inches) {
		int[] result = new int[2];
		result[0] = (int) inches/12;
		result[1] = (int) inches%12;
		return result;
	}
	
	/***
	 * Converts from feet and inches to inches
	 * @return total inches
	 */
	public int feetInchesToInches(int feet, int inches) {
		return feet * 12 + inches;
	}
	
	public boolean isMetricHeight() {
		return isMetricHeight;
	}
	
	public boolean isMetricWeight() {
		return isMetricWeight;
	}
	
	public boolean isStones() {
		return isStones;
	}
	
	public int getMinWeight() {
		if (isMetricWeight) {
			return METRIC_MIN_WEIGHT;
		}
		return IMPERIAL_MIN_WEIGHT;
	}
	
	public int getMaxWeight() {
		if (isMetricWeight) {
			return METRIC_MAX_WEIGHT;
		}
		return IMPERIAL_MAX_WEIGHT;
	}
	
	public int getDefaultWeight() {
		if (isMetricWeight) {
			return METRIC_DEFAULT_WEIGHT;
		}
		return IMPERIAL_DEFAULT_WEIGHT;
	}
	
	public int getMinHeight() {
		if (isMetricHeight) {
			return METRIC_MIN_HEIGHT;
		}
		return IMPERIAL_MIN_HEIGHT;
	}
	
	public int getMaxHeight() {
		if (isMetricHeight) {
			return METRIC_MAX_HEIGHT;
		}
		return IMPERIAL_MAX_HEIGHT;
	}
	
	public float getDefaultHeight() {
		if (isMetricHeight) {
			return METRIC_DEFAULT_HEIGHT;
		}
		return IMPERIAL_DEFAULT_HEIGHT;
	}

	public float getKCal() {
		if (isMetricWeight) {
			return KCAL_PER_KILOGRAM;
		}
		return KCAL_PER_POUND;
	}
}
